package cn.mujiankeji.mbrowser.功能.下载.工具

import android.util.Log

/**
 * M3U8播放列表解析器
 */
class M3U8解析器 {

    private val TAG = "M3U8解析器"

    // --- 数据类定义 ---
    /**
     * M3U8加密信息
     * @param method 加密方法 (NONE, AES-128, SAMPLE-AES)
     * @param uri 密钥文件的绝对URI
     * @param iv 初始化向量 (可选)
     * @param keyFormat 密钥格式 (可选, e.g., "identity", "com.apple.streamingkeydelivery")
     * @param keyFormatVersions 密钥格式版本 (可选)
     */
    data class M3U8KeyInfo(
        val method: String,
        val uri: String?,
        val iv: String? = null,
        val keyFormat: String? = "identity",
        val keyFormatVersions: String? = null
    )

    /**
     * M3U8媒体分片信息
     * @param uri 分片文件的绝对URI
     * @param duration 分片时长 (秒)
     * @param title 分片标题 (可选, 来自#EXTINF的描述)
     * @param sequenceNumber 媒体序列号 (隐式或显式)
     * @param discontinuity 是否表示不连续性
     * @param keyInfo 此分片应用的加密信息 (可能从全局继承)
     * @param byteRange 分片字节范围 (可选, e.g., "length@offset")
     */
    data class M3U8Segment(
        val uri: String,
        val duration: Float,
        val title: String? = null,
        val sequenceNumber: Int,
        var discontinuity: Boolean = false,
        var keyInfo: M3U8KeyInfo? = null,
        val byteRange: String? = null
    )

    /**
     * M3U8码流信息 (用于主播放列表)
     * @param uri 子M3U8播放列表的绝对URI
     * @param bandwidth 带宽 (bps)
     * @param averageBandwidth 平均带宽 (bps, 可选)
     * @param resolution 分辨率 (e.g., "1920x1080", 可选)
     * @param codecs 编解码器信息 (e.g., "avc1.42e01e,mp4a.40.2", 可选)
     * @param frameRate 帧率 (可选)
     * @param programId Program ID (已废弃但可能存在)
     */
    data class M3U8StreamInfo(
        val uri: String,
        val bandwidth: Long,
        val averageBandwidth: Long? = null,
        val resolution: String? = null,
        val codecs: String? = null,
        val frameRate: Float? = null,
        val programId: String? = null // 旧版字段
    )

    /**
     * M3U8播放列表解析结果
     * @param version M3U8版本号
     * @param targetDuration 最大分片时长 (秒)
     * @param mediaSequence 第一个分片的序列号
     * @param segments 媒体分片列表 (如果是媒体播放列表)
     * @param streamInfos 码流信息列表 (如果是主播放列表)
     * @param isMasterPlaylist 是否为主播放列表
     * @param isLivePlaylist 是否为直播流 (没有#EXT-X-ENDLIST)
     * @param globalKeyInfo 全局加密信息 (可能被分片级覆盖)
     */
    data class M3U8Playlist(
        val version: Int = 1,
        val targetDuration: Int = -1,
        val mediaSequence: Int = 0,
        val segments: List<M3U8Segment> = emptyList(),
        val streamInfos: List<M3U8StreamInfo> = emptyList(),
        val isMasterPlaylist: Boolean = false,
        var isLivePlaylist: Boolean = true, // 默认假设是直播，直到遇到ENDLIST
        var globalKeyInfo: M3U8KeyInfo? = null
        // 可以添加其他全局标签属性，如 PLAYLIST-TYPE 等
    )


    // --- 解析逻辑 ---

    /**
     * 解析M3U8播放列表内容。
     * @param m3u8Content M3U8文件的文本内容。
     * @param baseUrl M3U8文件本身的URL，用于解析相对路径的URI。
     * @return 解析后的 M3U8Playlist 对象。
     * @throws IllegalArgumentException 如果M3U8格式不正确或内容为空。
     */
    fun parse(m3u8Content: String, baseUrl: String): M3U8Playlist {
        if (m3u8Content.isBlank() || !m3u8Content.startsWith("#EXTM3U")) {
            throw IllegalArgumentException("无效的M3U8内容或非M3U8格式")
        }

        val lines = m3u8Content.lines().map { it.trim() }.filter { it.isNotEmpty() }

        var version = 1
        var targetDuration = -1
        var mediaSequence = 0
        var currentKeyInfo: M3U8KeyInfo? = null
        var nextSegmentDiscontinuity = false
        var nextSegmentByteRange: String? = null

        val segments = mutableListOf<M3U8Segment>()
        val streamInfos = mutableListOf<M3U8StreamInfo>()
        var isMasterPlaylist = false
        var isLivePlaylist = true // Assume live until #EXT-X-ENDLIST

        var segmentIndex = 0 // 用于生成隐式的媒体序列号（如果mediaSequence为0）

        for (i in lines.indices) {
            val line = lines[i]
            if (line.startsWith("#EXT")) {
                // 处理标签
                when {
                    line.startsWith("#EXT-X-VERSION:") -> {
                        version = line.substringAfter(":").toIntOrNull() ?: version
                    }
                    line.startsWith("#EXT-X-TARGETDURATION:") -> {
                        targetDuration = line.substringAfter(":").toIntOrNull() ?: targetDuration
                    }
                    line.startsWith("#EXT-X-MEDIA-SEQUENCE:") -> {
                        mediaSequence = line.substringAfter(":").toIntOrNull() ?: mediaSequence
                        segmentIndex = 0 // 重置基于mediaSequence的索引
                    }
                    line.startsWith("#EXT-X-KEY:") -> {
                        currentKeyInfo = parseKeyInfo(line.substringAfter(":"), baseUrl)
                    }
                    line.startsWith("#EXT-X-STREAM-INF:") -> {
                        isMasterPlaylist = true
                        // #EXT-X-STREAM-INF 标签下面紧跟着的是子播放列表的URI
                        if (i + 1 < lines.size && !lines[i + 1].startsWith("#")) {
                            val streamUri = lines[i + 1]
                            parseStreamInfo(line.substringAfter(":"), streamUri, baseUrl)?.let {
                                streamInfos.add(it)
                            }
                        }
                    }
                    line.startsWith("#EXTINF:") -> {
                        // #EXTINF 标签下面紧跟着的是分片URI
                        if (i + 1 < lines.size && !lines[i + 1].startsWith("#")) {
                            val segmentUri = lines[i + 1]
                            val (duration, title) = parseExtInf(line.substringAfter(":"))
                            segments.add(
                                M3U8Segment(
                                    uri = resolveUri(baseUrl, segmentUri),
                                    duration = duration,
                                    title = title,
                                    sequenceNumber = mediaSequence + segmentIndex,
                                    discontinuity = nextSegmentDiscontinuity,
                                    keyInfo = currentKeyInfo, // 应用当前解析到的密钥信息
                                    byteRange = nextSegmentByteRange
                                )
                            )
                            segmentIndex++
                            nextSegmentDiscontinuity = false // Reset for next segment
                            nextSegmentByteRange = null
                        }
                    }
                    line.startsWith("#EXT-X-DISCONTINUITY") -> {
                        nextSegmentDiscontinuity = true
                    }
                    line.startsWith("#EXT-X-BYTERANGE:") -> {
                        nextSegmentByteRange = line.substringAfter(":")
                    }
                    line.startsWith("#EXT-X-ENDLIST") -> {
                        isLivePlaylist = false
                    }
                    // TODO: 处理其他重要标签如 #EXT-X-PLAYLIST-TYPE, #EXT-X-MAP, etc.
                }
            } else if (!line.startsWith("#") && !isMasterPlaylist) {
                // 如果不是标签行，并且不是主播放列表（主播放列表的URI在#EXT-X-STREAM-INF后处理），
                // 那么这可能是一个没有#EXTINF的媒体分片URI (M3U8 v1, v2中可能出现)
                // 这种情况通常需要更复杂的处理或假设，对于现代M3U8较少见且不规范
                // Log.w(TAG, "发现一个没有#EXTINF的潜在分片URI: $line (可能是不规范的M3U8)")
            }
        }
        
        val finalPlaylist = M3U8Playlist(
            version = version,
            targetDuration = targetDuration,
            mediaSequence = mediaSequence,
            segments = segments,
            streamInfos = streamInfos,
            isMasterPlaylist = isMasterPlaylist,
            isLivePlaylist = isLivePlaylist,
            globalKeyInfo = if (segments.isNotEmpty() && segments.all { it.keyInfo == currentKeyInfo } ) currentKeyInfo else null
            // 更准确的globalKeyInfo是解析时遇到的第一个#EXT-X-KEY，如果没有被后续覆盖的话
        )
        Log.d(TAG, "M3U8解析完成: Master=${finalPlaylist.isMasterPlaylist}, Live=${finalPlaylist.isLivePlaylist}, Segments=${finalPlaylist.segments.size}, Streams=${finalPlaylist.streamInfos.size}")
        return finalPlaylist
    }

    /**
     * 解析#EXTINF标签内容。
     * 例如: "10.0,这是标题" 或 "10.0," 或 "10"
     * @return Pair(时长, 标题?)
     */
    private fun parseExtInf(extInfLine: String): Pair<Float, String?> {
        val parts = extInfLine.split(",", limit = 2)
        val duration = parts[0].toFloatOrNull() ?: 0f
        val title = if (parts.size > 1 && parts[1].isNotBlank()) parts[1] else null
        return Pair(duration, title)
    }

    /**
     * 解析#EXT-X-KEY标签内容。
     * 例如: METHOD=AES-128,URI="http://example.com/key.bin",IV=0x1234567890abcdef1234567890abcdef
     */
    private fun parseKeyInfo(keyLine: String, baseUrl: String): M3U8KeyInfo? {
        val attributes = parseAttributeList(keyLine)
        val method = attributes["METHOD"] ?: return null // METHOD is mandatory
        val uriString = attributes["URI"]?.let { resolveUri(baseUrl, it) }
        // IV, KEYFORMAT, KEYFORMATVERSIONS are optional
        val iv = attributes["IV"]
        val keyFormat = attributes["KEYFORMAT"] ?: "identity"
        val keyFormatVersions = attributes["KEYFORMATVERSIONS"]

        return M3U8KeyInfo(method, uriString, iv, keyFormat, keyFormatVersions)
    }

    /**
     * 解析#EXT-X-STREAM-INF标签内容和其后的URI。
     */
    private fun parseStreamInfo(streamInfLine: String, streamUri: String, baseUrl: String): M3U8StreamInfo? {
        val attributes = parseAttributeList(streamInfLine)
        val bandwidth = attributes["BANDWIDTH"]?.toLongOrNull() ?: return null // BANDWIDTH is mandatory
        val averageBandwidth = attributes["AVERAGE-BANDWIDTH"]?.toLongOrNull()
        val resolution = attributes["RESOLUTION"]
        val codecs = attributes["CODECS"]
        val frameRate = attributes["FRAME-RATE"]?.toFloatOrNull()
        val programId = attributes["PROGRAM-ID"] // Old, deprecated

        return M3U8StreamInfo(
            uri = resolveUri(baseUrl, streamUri),
            bandwidth = bandwidth,
            averageBandwidth = averageBandwidth,
            resolution = resolution,
            codecs = codecs,
            frameRate = frameRate,
            programId = programId
        )
    }
    
    /**
     * 辅助函数：解析属性列表字符串，如 "NAME="Value",NAME2="Value2"" 或 "NAME=Value,NAME2=Value2"
     * 处理带引号和不带引号的值。
     */
    private fun parseAttributeList(attributesString: String): Map<String, String> {
        val map = mutableMapOf<String, String>()
        // 正则表达式来匹配 KEY=VALUE 或 KEY="VALUE" 形式，支持逗号分隔
        // この正規表現は改善の余地があるかもしれません。特に複雑な属性文字列の場合。
        val regex = """([\w-]+)=("[^"]*"|[\w.-]+)""".toRegex()
        regex.findAll(attributesString).forEach { matchResult ->
            val key = matchResult.groupValues[1].uppercase() // 通常属性名は大文字・小文字を区別しないが、大文字に正規化
            var value = matchResult.groupValues[2]
            if (value.startsWith("\"") && value.endsWith("\"")) {
                value = value.substring(1, value.length - 1) // Remove quotes
            }
            map[key] = value
        }
        return map
    }


    /**
     * 根据基础URL解析相对URI。
     */
    private fun resolveUri(baseUrlString: String, relativeUriString: String): String {
        // 如果relativeUri已经是绝对URI，直接返回
        if (relativeUriString.startsWith("http://") || relativeUriString.startsWith("https://")) {
            return relativeUriString
        }
        
        return try {
            // 创建java.net.URL来正确处理相对路径解析
            val baseUrl = java.net.URL(baseUrlString)
            val resolvedUrl = java.net.URL(baseUrl, relativeUriString)
            resolvedUrl.toString()
        } catch (e: Exception) {
            Log.w(TAG, "解析URI失败: baseUrl=$baseUrlString, relativeUri=$relativeUriString", e)
            // 简单拼接作为后备方案
            if (baseUrlString.endsWith("/") || relativeUriString.startsWith("/")) {
                baseUrlString + relativeUriString
            } else {
                "$baseUrlString/$relativeUriString"
            }
        }
    }
} 